﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Upreader.Engine;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;

namespace Upreader.Presentation.Client.ViewModel
{
    [Export]
    public class ServerViewModel : ViewModelBase<ServerViewModel>
    {
        #region Configuration

        private const int StatisticsUpdateTimerFrequency = 100;

        #endregion // Configuration

        #region Fields

        private ServerProcessor _serverProcessor;
        private Timer _statisticsUpdateTimer;

        private readonly ObservableCollection<ConnectionViewModel> _connections;

        private long _totalBytesSent;
        private long _totalBytesReceived;

        #endregion // Fields

        #region Constructor

        public ServerViewModel(ServerProcessor serverProcessor)
        {
            _connections = new ObservableCollection<ConnectionViewModel>();
        }

        #endregion // Constructor

        #region Properties

        public ServerProcessor ServerProcessor
        {
            get { return _serverProcessor; }
            set
            {
                if (_serverProcessor != null)
                    throw new InvalidOperationException("Can set the ServerProcessor only once");
                if (value == null)
                    throw new ArgumentNullException("serverProcessor");

                _serverProcessor = value;
                _statisticsUpdateTimer = new Timer(new TimerCallback(_ => OnStatisticsUpdateTimerHit()), null, 0, StatisticsUpdateTimerFrequency);
            }
        }

        public long TotalBytesSent
        {
            get { return _totalBytesSent; }
            set
            {
                if (_totalBytesSent != value)
                {
                    _totalBytesSent = value;

                    RaisePropertyChanged(x => x.TotalBytesSent);
                }
            }
        }

        public long TotalBytesReceived
        {
            get { return _totalBytesReceived; }
            set
            {
                if (_totalBytesReceived != value)
                {
                    _totalBytesReceived = value;

                    RaisePropertyChanged(x => x.TotalBytesReceived);
                }
            }
        }

        public ReadOnlyObservableCollection<ConnectionViewModel> Connections
        {
            get { return new ReadOnlyObservableCollection<ConnectionViewModel>(_connections); }
        }

        #endregion // Properties

        #region EventHandlers

        protected void OnStatisticsUpdateTimerHit()
        {
            long totalBytesSent = _serverProcessor.CalculateTotalBytesSent();
            long totalBytesReceived = _serverProcessor.CalculateTotalBytesReceived();

            if (totalBytesReceived != TotalBytesReceived || totalBytesSent != TotalBytesSent)
            
            BeginInvoke(() =>
            {
                TotalBytesSent = totalBytesSent;
                TotalBytesReceived = totalBytesReceived;
            });
        }

        #endregion // EventHandlers

        #region Cleanup

        protected override void Dispose(bool disposing)
        {
            _statisticsUpdateTimer.Dispose();
        }

        #endregion // Cleanup
    }
}
